home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / input / input_dec.c < prev    next >
C/C++ Source or Header  |  2003-04-07  |  13KB  |  369 lines

  1. /*****************************************************************************
  2.  * input_dec.c: Functions for the management of decoders
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2001 VideoLAN
  5.  * $Id: input_dec.c,v 1.59 2003/03/04 13:21:19 massiot Exp $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23.  
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>
  28. #include <string.h>                                    /* memcpy(), memset() */
  29.  
  30. #include <vlc/vlc.h>
  31.  
  32. #include "stream_control.h"
  33. #include "input_ext-dec.h"
  34. #include "input_ext-intf.h"
  35. #include "input_ext-plugins.h"
  36.  
  37. static decoder_fifo_t * CreateDecoderFifo( input_thread_t *,
  38.                                            es_descriptor_t * );
  39. static void             DeleteDecoderFifo( decoder_fifo_t * );
  40.  
  41. /*****************************************************************************
  42.  * input_RunDecoder: spawns a new decoder thread
  43.  *****************************************************************************/
  44. decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
  45.                                    es_descriptor_t * p_es )
  46. {
  47.     char           *psz_sout;
  48.     decoder_fifo_t *p_fifo;
  49.     int i_priority;
  50.  
  51.     /* Create the decoder configuration structure */
  52.     p_fifo = CreateDecoderFifo( p_input, p_es );
  53.  
  54.     if( p_fifo == NULL )
  55.     {
  56.         msg_Err( p_input, "could not create decoder fifo" );
  57.         return NULL;
  58.     }
  59.  
  60.     p_fifo->p_module = NULL;
  61.     /* If we are in sout mode, search first for packetizer module then
  62.      * codec to do transcoding */
  63.     psz_sout = config_GetPsz( p_input, "sout" );
  64.     if( psz_sout != NULL && *psz_sout != 0 )
  65.     {
  66.         vlc_bool_t b_sout = VLC_TRUE;
  67.  
  68.         if( p_es->i_cat == AUDIO_ES )
  69.         {
  70.             b_sout = config_GetInt( p_input, "sout-audio" );
  71.         }
  72.         else if( p_es->i_cat == VIDEO_ES )
  73.         {
  74.             b_sout = config_GetInt( p_input, "sout-video" );
  75.         }
  76.  
  77.         if( b_sout )
  78.         {
  79.             vlc_bool_t b_reencode = VLC_FALSE;
  80.  
  81.             if( p_es->i_cat == AUDIO_ES )
  82.             {
  83.                 char *psz_sout_acodec = config_GetPsz( p_input, "sout-acodec" );
  84.                 if( psz_sout_acodec != NULL && *psz_sout_acodec != '\0' )
  85.                 {
  86.                     msg_Dbg( p_input, "audio reencoding requested -> unsupported" );
  87.                     b_reencode = VLC_TRUE;
  88.                 }
  89.             }
  90.             else if( p_es->i_cat == VIDEO_ES )
  91.             {
  92.                 char *psz_sout_vcodec = config_GetPsz( p_input, "sout-vcodec" );
  93.                 if( psz_sout_vcodec != NULL && *psz_sout_vcodec != '\0' )
  94.                 {
  95.                     msg_Dbg( p_input, "video reencoding requested" );
  96.                     /* force encoder video output */
  97.                     config_PutPsz( p_input, "vout", "encoder" );
  98.                     b_reencode = VLC_TRUE;
  99.                 }
  100.             }
  101.  
  102.             if( !b_reencode )
  103.             {
  104.                 /* we don't want to reencode so search for a packetizer */
  105.                 p_fifo->p_module =
  106.                     module_Need( p_fifo, "packetizer", "$packetizer" );
  107.             }
  108.             else
  109.             {
  110.                 /* get a suitable decoder module to do reencoding*/
  111.                 p_fifo->p_module = module_Need( p_fifo, "decoder", "$codec" );
  112.             }
  113.         }
  114.     }
  115.     else
  116.     {
  117.         /* default Get a suitable decoder module */
  118.         p_fifo->p_module = module_Need( p_fifo, "decoder", "$codec" );
  119.     }
  120.  
  121.     if( p_fifo->p_module == NULL )
  122.     {
  123.         msg_Err( p_fifo, "no suitable decoder module for fourcc `%4.4s'.\nVLC probably does not support this sound or video format.",
  124.                        (char*)&p_fifo->i_fourcc );
  125.         DeleteDecoderFifo( p_fifo );
  126.         vlc_object_destroy( p_fifo );
  127.         return NULL;
  128.     }
  129.  
  130.     if ( p_es->i_cat == AUDIO_ES )
  131.     {
  132.         i_priority = VLC_THREAD_PRIORITY_AUDIO;
  133.     }
  134.     else
  135.     {
  136.         i_priority = VLC_THREAD_PRIORITY_VIDEO;
  137.     }
  138.  
  139.     /* Spawn the decoder thread */
  140.     if( vlc_thread_create( p_fifo, "decoder", p_fifo->pf_run,
  141.                            i_priority, VLC_FALSE ) )
  142.     {
  143.         msg_Err( p_fifo, "cannot spawn decoder thread \"%s\"",
  144.                          p_fifo->p_module->psz_object_name );
  145.         module_Unneed( p_fifo, p_fifo->p_module );
  146.         return NULL;
  147.     }
  148.  
  149.     p_input->stream.b_changed = 1;
  150.  
  151.     return p_fifo;
  152. }
  153.  
  154.  
  155. /*****************************************************************************
  156.  * input_EndDecoder: kills a decoder thread and waits until it's finished
  157.  *****************************************************************************/
  158. void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
  159. {
  160.     int i_dummy;
  161.  
  162.     p_es->p_decoder_fifo->b_die = 1;
  163.  
  164.     /* Make sure the thread leaves the NextDataPacket() function by
  165.      * sending it a few null packets. */
  166.     for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
  167.     {
  168.         input_NullPacket( p_input, p_es );
  169.     }
  170.  
  171.     if( p_es->p_pes != NULL )
  172.     {
  173.         input_DecodePES( p_es->p_decoder_fifo, p_es->p_pes );
  174.     }
  175.  
  176.     /* Waiting for the thread to exit */
  177.     /* I thought that unlocking was better since thread join can be long
  178.      * but it actually creates late pictures and freezes --stef */
  179.     /* vlc_mutex_unlock( &p_input->stream.stream_lock ); */
  180.     vlc_thread_join( p_es->p_decoder_fifo );
  181.     /* vlc_mutex_lock( &p_input->stream.stream_lock ); */
  182.  
  183.     /* Delete decoder configuration */
  184.     DeleteDecoderFifo( p_es->p_decoder_fifo );
  185.  
  186.     /* Unneed module */
  187.     module_Unneed( p_es->p_decoder_fifo, p_es->p_decoder_fifo->p_module );
  188.  
  189.     /* Delete the fifo */
  190.     vlc_object_destroy( p_es->p_decoder_fifo );
  191.  
  192.     /* Tell the input there is no more decoder */
  193.     p_es->p_decoder_fifo = NULL;
  194.  
  195.     p_input->stream.b_changed = 1;
  196. }
  197.  
  198. /*****************************************************************************
  199.  * input_DecodePES
  200.  *****************************************************************************
  201.  * Put a PES in the decoder's fifo.
  202.  *****************************************************************************/
  203. void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
  204. {
  205.     vlc_mutex_lock( &p_decoder_fifo->data_lock );
  206.  
  207.     p_pes->p_next = NULL;
  208.     *p_decoder_fifo->pp_last = p_pes;
  209.     p_decoder_fifo->pp_last = &p_pes->p_next;
  210.     p_decoder_fifo->i_depth++;
  211.  
  212.     /* Warn the decoder that it's got work to do. */
  213.     vlc_cond_signal( &p_decoder_fifo->data_wait );
  214.     vlc_mutex_unlock( &p_decoder_fifo->data_lock );
  215. }
  216.  
  217. /*****************************************************************************
  218.  * Create a NULL packet for padding in case of a data loss
  219.  *****************************************************************************/
  220. void input_NullPacket( input_thread_t * p_input,
  221.                        es_descriptor_t * p_es )
  222. {
  223.     data_packet_t *             p_pad_data;
  224.     pes_packet_t *              p_pes;
  225.  
  226.     if( (p_pad_data = input_NewPacketForce( p_input->p_method_data,
  227.                     PADDING_PACKET_SIZE)) == NULL )
  228.     {
  229.         msg_Err( p_input, "no new packet" );
  230.         p_input->b_error = 1;
  231.         return;
  232.     }
  233.  
  234.     memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
  235.     p_pad_data->b_discard_payload = 1;
  236.     p_pes = p_es->p_pes;
  237.  
  238.     if( p_pes != NULL )
  239.     {
  240.         p_pes->b_discontinuity = 1;
  241.         p_pes->p_last->p_next = p_pad_data;
  242.         p_pes->p_last = p_pad_data;
  243.         p_pes->i_nb_data++;
  244.     }
  245.     else
  246.     {
  247.         if( (p_pes = input_NewPES( p_input->p_method_data )) == NULL )
  248.         {
  249.             msg_Err( p_input, "no PES packet" );
  250.             p_input->b_error = 1;
  251.             return;
  252.         }
  253.  
  254.         p_pes->i_rate = p_input->stream.control.i_rate;
  255.         p_pes->p_first = p_pes->p_last = p_pad_data;
  256.         p_pes->i_nb_data = 1;
  257.         p_pes->b_discontinuity = 1;
  258.         input_DecodePES( p_es->p_decoder_fifo, p_pes );
  259.     }
  260. }
  261.  
  262. /*****************************************************************************
  263.  * input_EscapeDiscontinuity: send a NULL packet to the decoders
  264.  *****************************************************************************/
  265. void input_EscapeDiscontinuity( input_thread_t * p_input )
  266. {
  267.     unsigned int i_es, i;
  268.  
  269.     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
  270.     {
  271.         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
  272.  
  273.         if( p_es->p_decoder_fifo != NULL )
  274.         {
  275.             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
  276.             {
  277.                 input_NullPacket( p_input, p_es );
  278.             }
  279.         }
  280.     }
  281. }
  282.  
  283. /*****************************************************************************
  284.  * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
  285.  *****************************************************************************/
  286. void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
  287. {
  288.     unsigned int i_es, i;
  289.  
  290.     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
  291.     {
  292.         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
  293.  
  294.         if( p_es->p_decoder_fifo != NULL && p_es->i_cat == AUDIO_ES )
  295.         {
  296.             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
  297.             {
  298.                 input_NullPacket( p_input, p_es );
  299.             }
  300.         }
  301.     }
  302. }
  303.  
  304. /*****************************************************************************
  305.  * CreateDecoderFifo: create a decoder_fifo_t
  306.  *****************************************************************************/
  307. static decoder_fifo_t * CreateDecoderFifo( input_thread_t * p_input,
  308.                                            es_descriptor_t * p_es )
  309. {
  310.     decoder_fifo_t * p_fifo;
  311.  
  312.     /* Decoder FIFO */
  313.     p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER );
  314.     if( p_fifo == NULL )
  315.     {
  316.         msg_Err( p_input, "out of memory" );
  317.         return NULL;
  318.     }
  319.  
  320.     /* Select a new ES */
  321.     INSERT_ELEM( p_input->stream.pp_selected_es,
  322.                  p_input->stream.i_selected_es_number,
  323.                  p_input->stream.i_selected_es_number,
  324.                  p_es );
  325.  
  326.     /* Initialize the p_fifo structure */
  327.     vlc_mutex_init( p_input, &p_fifo->data_lock );
  328.     vlc_cond_init( p_input, &p_fifo->data_wait );
  329.     p_es->p_decoder_fifo = p_fifo;
  330.  
  331.     p_fifo->i_id = p_es->i_id;
  332.     p_fifo->i_fourcc = p_es->i_fourcc;
  333.     p_fifo->p_demux_data   = p_es->p_demux_data;
  334.     p_fifo->p_waveformatex = p_es->p_waveformatex;
  335.     p_fifo->p_bitmapinfoheader = p_es->p_bitmapinfoheader;
  336.     p_fifo->p_stream_ctrl = &p_input->stream.control;
  337.     p_fifo->p_sout = p_input->stream.p_sout;
  338.  
  339.     p_fifo->p_first = NULL;
  340.     p_fifo->pp_last = &p_fifo->p_first;
  341.     p_fifo->i_depth = 0;
  342.     p_fifo->b_die = p_fifo->b_error = 0;
  343.     p_fifo->p_packets_mgt = p_input->p_method_data;
  344.  
  345.     vlc_object_attach( p_fifo, p_input );
  346.  
  347.     return p_fifo;
  348. }
  349.  
  350. /*****************************************************************************
  351.  * DeleteDecoderFifo: destroy a decoder_fifo_t
  352.  *****************************************************************************/
  353. static void DeleteDecoderFifo( decoder_fifo_t * p_fifo )
  354. {
  355.     vlc_object_detach( p_fifo );
  356.  
  357.     msg_Dbg( p_fifo, "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO",
  358.                      p_fifo->i_id, (char*)&p_fifo->i_fourcc, p_fifo->i_depth );
  359.  
  360.     /* Free all packets still in the decoder fifo. */
  361.     input_DeletePES( p_fifo->p_packets_mgt,
  362.                      p_fifo->p_first );
  363.  
  364.     /* Destroy the lock and cond */
  365.     vlc_cond_destroy( &p_fifo->data_wait );
  366.     vlc_mutex_destroy( &p_fifo->data_lock );
  367. }
  368.  
  369.